﻿using Newtonsoft.Json;
using Prism.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using ZoneLineNew.Common;
using ZoneLineNew.Enums;
using ZoneLineNew.Models.StationConfig;
using ZoneLineNew.Models.StationResult.QOPStation;
using ZoneLineNew.Services.DB;
using ZoneLineNew.Services.Print;

namespace ZoneLineNew.Services.Station.QOPStation {
    /// <summary>
    /// 补偿垫片装配工位
    /// </summary>
    /// <remarks>
    /// <para>StationCode：OP560</para>
    /// <para>IP：192.168.10.55</para>
    /// </remarks>
    public class QOP020StationService : WorkStationBaseService<QOP020StationResult, QOP020StationConfig> {

        private float _currentMesRlt = 0.0f;
        private StationDataResult _currentStationDataResult = null;

        public QOP020StationService(
            IDbOperate<IFreeSqlMainContext> mainDbOperate, 
            IEventAggregator eventAggregator,
            PrinterLabelService printerService
            )
            : base(mainDbOperate, eventAggregator, printerService) {

            _ = Task.Factory.StartNew(() => {
                if (IsConnected) {
                    base.WriteData("DB1001.14", (short)Cache.CurWorkProduct.WorkDirection);
                    base.WriteData("DB1001.2168", Cache.CurWorkProduct.ProductName);
                }
            });

            Task.Run(() => {
                GetStationFromMes();
            });

            base.InitReSetAddr();
        }

        private string _mesStationNo;
        /// <summary>
        /// 
        /// </summary>
        public string MesStationNo {
            get { return _mesStationNo; }
            set => SetProperty(ref _mesStationNo, value);
        }

        private int _productChannel;
        /// <summary>
        /// 指定产品通道
        /// </summary>
        public int ProductChannel {
            get { return _productChannel; }
            set => SetProperty(ref _productChannel, value);
        }


        public override void DealData(byte[] content) {
            StationRecordData.AbsScanCode = GetPlcString(content, 280);
            StationRecordData.SpringCode = GetPlcString(content, 322);
            if (!string.IsNullOrWhiteSpace(StationRecordData.SpringCode)) {
                //之前X04读取方式
                //StationRecordData.SpringCode = GetPlcString(content, 322).Substring(0, 6);
                //弹簧码发生改变（字母+数字）
                StationRecordData.SpringCode = Regex.Replace(GetPlcString(content, 322), @"[^\d.\d]", "");
            }
            StationRecordData.PartType = GetPlcString(content, 1002);
            StationRecordData.Result = _client.ByteTransform.TransInt16(content, 1000).ToString().Equals("1") ? "OK" : "NG";
            StationRecordData.ShimValue = _client.ByteTransform.TransSingle(content, 1016);
            StationRecordData.WorkChannel = Convert.ToInt32(_client.ReadInt16("DB1001.6").Content);

            //批次追溯
            StationRecordData.SpringBatchCode = _client.ReadString("DB1100.DBX0").Content;
            StationRecordData.Shim1_4 = _client.ReadString("DB1100.DBX50").Content;
            StationRecordData.Shim2_8 = _client.ReadString("DB1100.DBX100").Content;
            StationRecordData.Shim4_2 = _client.ReadString("DB1100.DBX150").Content;
            StationRecordData.Shim5_6 = _client.ReadString("DB1100.DBX200").Content;
        }

        public override void DealWithCommonData(byte[] content) {
            Heart = _client.ByteTransform.TransInt16(content, 8) == (short)1;
            StartUploadCode = _client.ByteTransform.TransInt16(content, 6) == (short)1;
            StartUploadData = _client.ByteTransform.TransInt16(content, 10) == (short)1;

            HeartToPlc = _client.ReadInt16("DB1001.DBW0").Content == (short)1;
            EndUpLoadCode = _client.ReadInt16("DB1001.8").Content == (short)1;
            EndUpLoadData = _client.ReadInt16("DB1001.2").Content == (short)1;
            AllowWork = _client.ReadInt16("DB1001.8").Content;
            ProductChannel = _client.ReadInt16("DB1001.6").Content;
        }

        public override async void DealWithSignal(string signalName) {

            if (signalName == nameof(StartUploadCode))
            {
                //todo 上传了条码 这时候验证是否要工作
                if (StartUploadCode == false)
                {
                    LogWithUi($"在{CurrentStationName}收到上传条码命令变为false", StationRecordData.AbsScanCode);
                    WriteData(StationConfig.EndUploadCodeAddr, 0, StationRecordData.AbsScanCode);
                    WriteData(StationConfig.AllowWorkAddr, 0, StationRecordData.AbsScanCode);
                    LogWithUi($"在{CurrentStationName}复位工作控制指令和复位上传条码完成指令", StationRecordData.AbsScanCode);
                }
                else
                {
                    _currentMesRlt = 0.0f;
                    _currentStationDataResult = null;
                    LogWithUi($"在{CurrentStationName}收到上传条码信息命令", StationRecordData.AbsScanCode);

                    #region 验证缸体码是否合格
                    LogWithUi($"在{CurrentStationName}工位检查缸体码是否合格", StationRecordData.AbsScanCode);
                    var codeRes = base.MainCodeVerify(StationRecordData.AbsScanCode);
                    LogWithUi($"在{CurrentStationName}工位检查缸体码是否合格{StationRecordData.AbsScanCode}的结论是{codeRes}", StationRecordData.AbsScanCode);
                    if (!codeRes) {
                        LogWithUi($"在{CurrentStationName}工位检查缸体码不合格", StationRecordData.AbsScanCode);
                        var writeRlt0 = WriteWorkActionToPlc(StationConfig.AllowWorkAddr, WorkActionEnum.CodeErr, StationRecordData.AbsScanCode);
                        LogWithUi($"在{CurrentStationName}工位向下位机下发消息，下发{writeRlt0}", StationRecordData.AbsScanCode);
                        return;
                    }
                    #endregion

                    LogWithUi($"在{CurrentStationName}工位结论验证,条码信息是{StationRecordData.AbsScanCode}", StationRecordData.AbsScanCode);
                    var validataResultTemp = Validata(CurrentStationName, StationRecordData.AbsScanCode);
                    //验证通过，开始api验证
                    var validataResult = validataResultTemp;
                    if (validataResultTemp == WorkActionEnum.StartWork && StationConfig.EnableApi)
                    {
                        int currentCount = 0;
                        while (currentCount <= StationConfig.ReQueryCount)
                        {
                            currentCount++;
                            //OP150
                            if (string.IsNullOrEmpty(MesStationNo))
                            {
                                LogWithUi($"在{CurrentStationName}工位从mes获取工位编号信息", StationRecordData.AbsScanCode);
                                long stationIdBase = 1656504687085625344;
                                var stationInfoResult = await ApiHelper.GetStaionInfo(StationConfig.ApiUrl);
                                if (stationInfoResult.IsSuccess)
                                {
                                    MesStationNo = stationInfoResult.data.list.FirstOrDefault(p => p.id == stationIdBase)?.id.ToString();
                                }
                                else
                                {
                                    LogWithUi($"在{CurrentStationName}工位从mes获取工位编号信息失败", StationRecordData.AbsScanCode);
                                    validataResult = WorkActionEnum.CalHErr;
                                }
                            }

                            if (!string.IsNullOrEmpty(MesStationNo))
                            {
                                try
                                {
                                    var (mesResult, calRlt, channel, stationDataResult) = CalChannel(StationRecordData.AbsScanCode, StationRecordData.SpringCode).GetAwaiter().GetResult();
                                    _currentMesRlt = mesResult;
                                    _currentStationDataResult = stationDataResult;
                                    LogWithUi($"计算高度成功，使用通道号信息{channel}", StationRecordData.AbsScanCode);
                                    WriteData(StationConfig.WorkChannelAddr, channel, StationRecordData.AbsScanCode);
                                    break;
                                }
                                catch (TaskCanceledException ex)
                                {
                                    LogWithUi($"从Mes系统获取数据失败，mes系统不返回数据", StationRecordData.AbsScanCode);
                                    validataResult = WorkActionEnum.CalHErr;
                                }
                                catch (Exception ex)
                                {
                                    LogWithUi($"计算高度差失败，失败原因是{ex.Message}", StationRecordData.AbsScanCode);
                                    validataResult = WorkActionEnum.CalHErr;
                                }
                            }
                            Thread.Sleep(1000);
                        }
                    }

                    #region 检查来料是否合格
                    LogWithUi($"在{CurrentStationName}检查来料是否合格", StationRecordData.AbsScanCode);
                    var mesRes = await ApiHelper.CheckIncomingMaterialIsOKAsync(StationRecordData.AbsScanCode, _currentStationDataResult);
                    LogWithUi($"在{CurrentStationName}{mesRes.errorMsg}", StationRecordData.AbsScanCode);
                    if (!mesRes.IsOk)
                    {
                        validataResult = WorkActionEnum.CalHErr;
                        LogWithUi($"在{CurrentStationName}{mesRes.errorMsg}", StationRecordData.AbsScanCode);
                    }
                    #endregion

                    LogWithUi($"在{CurrentStationName}工位结论验证,验证结论是{validataResult.ToString()}", StationRecordData.AbsScanCode);
                    var writeToRlt = WriteWorkActionToPlc(StationConfig.AllowWorkAddr, validataResult, StationRecordData.AbsScanCode, true);
                    if (writeToRlt)
                    {
                        LogWithUi($"在{CurrentStationName}向下个工位写入控制命令成功", StationRecordData.AbsScanCode);
                    }
                    else
                    {
                        LogWithUi($"在{CurrentStationName}向下个工位写入控制命令失败", StationRecordData.AbsScanCode);
                    }
                }
                return;
            }

            if (signalName == nameof(StartUploadData))
            {
                //todo 上传数据 这时候将数据记录到数据库中
                if (StartUploadData)
                {
                    LogWithUi($"在{CurrentStationName}收到上传记录数据命令", StationRecordData.AbsScanCode);
                    var rlt = RecordData();
                    WriteData(StationConfig.EndUploadDataAddr, (short)rlt, StationRecordData.AbsScanCode, true);
                    LogWithUi($"在{CurrentStationName}数据记录,rlt={rlt}", StationRecordData.AbsScanCode);
                }
                else
                {
                    LogWithUi($"在{CurrentStationName}收到上传记录数据命令变为false", StationRecordData.AbsScanCode);

                    WriteData(StationConfig.EndUploadDataAddr, 0, StationRecordData.AbsScanCode, true);
                    LogWithUi($"在{CurrentStationName}数据记录,clear", StationRecordData.AbsScanCode);
                    _currentMesRlt = 0.0f;
                    _currentStationDataResult = null;
                }
            }
        }

        public override int RecordData() {
            LogWithUi($"在{CurrentStationName}工位开始保存数据开始", StationRecordData.AbsScanCode);
            var result = new QOP020StationResult() {
                StationCode = base.StationConfig.StationCode,
                AbsScanCode = StationRecordData.AbsScanCode,
                Result = StationRecordData.Result,
                ShimValue = StationRecordData.ShimValue,
                PartType = StationRecordData.PartType,
                WorkChannel = StationRecordData.WorkChannel,
                SpringCode = StationRecordData.SpringCode,
                AirSpring = _currentMesRlt,
                CreateTime = DateTime.Now,
                ProductID = Cache.CurWorkProduct.Id,
                //以下是批次追溯
                SpringBatchCode = StationRecordData.SpringBatchCode,
                Shim1_4 = StationRecordData.Shim1_4,
                Shim2_8 = StationRecordData.Shim2_8,
                Shim4_2 = StationRecordData.Shim4_2,
                Shim5_6 = StationRecordData.Shim5_6,
            };
            var writeRlt = false;
            if (_mainDbOperate.CheckExist<QOP020StationResult>(p => p.AbsScanCode == result.AbsScanCode && !result.IsReworked)) {
                var beforeRlt = _mainDbOperate.GetModel<QOP020StationResult>(p => p.AbsScanCode == result.AbsScanCode && !result.IsReworked);
                result.Id = beforeRlt.Id;
                writeRlt = _mainDbOperate.UpdateModelSuper<QOP020StationResult>(p => p.AbsScanCode == result.AbsScanCode && !result.IsReworked, result);
                LogWithUi($"在{CurrentStationName}工位数据更新,rlt={writeRlt}", StationRecordData.AbsScanCode);
            } else {
                writeRlt = _mainDbOperate.AddModel(result);
                LogWithUi($"在{CurrentStationName}工位数据新增,rlt={writeRlt}", StationRecordData.AbsScanCode);
            }
            LogWithUi($"在{CurrentStationName}工位开始保存数据完成", StationRecordData.AbsScanCode);
            return writeRlt ? 1 : 2;
        }


        private async void GetStationFromMes() {
            while (string.IsNullOrEmpty(MesStationNo)) {
                try {
                    LogWithUi($"开始获取工位编号", StationRecordData.AbsScanCode);
                    long stationIdBase = 1656504687085625344;
                    var stationInfoResult = await ApiHelper.GetStaionInfo(StationConfig.ApiUrl);
                    LogWithUi($"获取工位编号信息返回" + JsonConvert.SerializeObject(stationInfoResult), StationRecordData.AbsScanCode);
                    if (stationInfoResult.IsSuccess) {
                        MesStationNo = stationInfoResult.data.list.FirstOrDefault(p => p.id == stationIdBase)?.id.ToString();
                        if (!string.IsNullOrEmpty(MesStationNo)) {
                            break;
                        }
                    }
                } catch (Exception ex) {
                    LogWithUi($"获取工位编号失败，失败原因是{ex.Message}", StationRecordData.AbsScanCode);
                }
                Thread.Sleep(2000);
            }
        }

        /// <summary>
        /// </summary>
        /// <param name="absCode">工件码</param>
        /// <param name="springCode">弹簧力</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        private async Task<(float, float, short, StationDataResult)> CalChannel(string absCode, string springCode) {
            //弹簧设计载荷: a，气体反弹力: b; 高度偏差: H
            if (string.IsNullOrEmpty(MesStationNo)) {
                throw new Exception("系统没有获取到工位编号，不能计算");
            }
            float springValue = default;
            //弹簧码发生改变（字母+数字）
            LogWithUi($"在{CurrentStationName}工位从mes获取弹簧力信息{springCode}", StationRecordData.AbsScanCode);
            if (!float.TryParse(springCode, out springValue)) {
                throw new Exception("弹簧设计载荷转换异常，不能计算");
            }

            LogWithUi($"在{CurrentStationName}工位从mes获取弹簧力信息", StationRecordData.AbsScanCode);
            var queryStr = $"{{\"Body\":\"{{stationId:\\\"{MesStationNo}\\\",masterCode:\\\"{absCode}\\\"}}\"}}";
            LogWithUi($"在{CurrentStationName}工位发送{queryStr}数据到mes", StationRecordData.AbsScanCode);
            var (stationData, apiRlt) = await ApiHelper.GetStationData(queryStr, StationConfig.ApiUrl);
            LogWithUi($"在{CurrentStationName}mes工位返回信息是:{apiRlt}", StationRecordData.AbsScanCode);
            if (stationData.IsSuccess) {
                if (stationData.data != null) {
                    LogWithUi($"在{CurrentStationName}工位获取弹簧力信息成功", StationRecordData.AbsScanCode);
                    var data = stationData.data.FirstOrDefault(p => p.parameterConfigName == "反弹力")?.parameterValue;
                    LogWithUi($"在{CurrentStationName}工位获取弹簧力信息是{data}", StationRecordData.AbsScanCode);
                    if (float.TryParse(data, out float result)) {
                        //float H = (float)((springValue - 7798.5f) / 53 + (result - 125) / 53 + 3.5);
                        float H = (float)((springValue - 7798.5f) / 53 + (result - 155) / 53 + 3.5);//20250422 update 客户确认将125修改为155
                        short channel = 0;
                        if (0 <= H && H <= 1.4) {
                            //使用通道1
                            channel = 1;
                        } else if (1.4 < H && H <= 2.8) {
                            //使用通道2
                            channel = 2;
                        } else if (2.8 < H && H <= 4.2) {
                            //使用通道3
                            channel = 3;
                        } else if (4.2 < H && H <= 5.6) {
                            //使用通道4
                            channel = 4;
                        } else if (5.6 < H && H <= 7) {
                            //使用通道5
                            channel = 5;
                        } else {
                            throw new Exception($"高度偏差数据计算结果是{H},超限报警");
                        }
                        return (result, H, channel, stationData);
                    } else {
                        throw new Exception("获取到的弹簧力信息不正确不能转换");
                    }
                } else {
                    LogWithUi($"在{CurrentStationName}工位获取弹簧力信息为空，请检查", StationRecordData.AbsScanCode);
                    throw new Exception("获取到的弹簧力数据为空");
                }
            } else {
                LogWithUi($"在{CurrentStationName}工位获取弹簧力信息失败", StationRecordData.AbsScanCode);
                throw new Exception("获取弹簧力信息失败");
            }
        }

    }

}
